<?php
namespace interface\v1;
/*
*考勤接口类
*/
class workSignAppClass extends index {
	/*行政人事-考勤记录*/
	public function home(){
		$staff = query("staff"," stid = '".$this->post['stid']."' ");
		if(!$this->power("workSign","seeAll")){
			$json['warn'] = "您没有查看所有员工考勤的权限";
		}elseif(empty($this->post['stid'])){
			$json = $this->face(array("staff" => $this->control));
		}elseif(empty($staff['stid'])){
			$json['warn'] = "未找到此员工";
		}else{
			$json = $this->face(array("staff" => $staff));
		}
		return $json;
	}
	/*个人中心-我的考勤*/
	public function my(){
		return $this->face(array("staff" => $this->control));
	}
	/*考勤面板
	$data = array(
		"stid" => 员工ID,
	);
	*/
	public function face($data){
		//月份
		if(empty($this->post['month'])){
			$this->post['month'] = date("Y-m");
		}elseif(preg_match(checkYmLine,$this->post['month']) == 0){
			$json['warn'] = "月份格式必须为YYYY-MM";
		}
		//返回
		if(empty($json['warn'])){
			$json = $this->table(array("month" => $this->post['month'],"staff" => $data['staff']));
		}
		return $json;
	}
	/*打印结果*/
	public function table($data){
		//分析日历
		$calendar = $this->calendar(array("staff" => $data['staff'],"month" => $data['month']));
		//婚假小时数
		if($calendar['marry'] > 24){
			$marry = 24;
		}else{
			$marry = $calendar['marry'];
		}
		//本月开始时间和结束时间
		$monthStart = $data['month']."-01 00:00:00";
		$monthEnd = $calendar['lastDay']." 24:00:00";
		//加班小时数，加班开始时间在本月即记为本月加班
		$workAddHour = find(array("table" => "work_add","sum" => "hour","where" => " stid = '".$data['staff']['stid']."' and timeStart > '$monthStart' and timeStart <= '$monthEnd' and workFlow = '已通过' "));
		//薪酬核算
		$lawHour = $calendar['workDayNum']*8;//本月法定小时数
		$ymh = $this->ymh(array("month" => $data['month']));//本年每月平均法定小时数
		$hourAll = round($calendar['workHour']+$marry+$workAddHour,2);//实到
		$job = query("job"," id = '".$data['staff']['jobId']."' ");
		$department = query("department"," id = '".$job['departmentId']."' ");
		if($hourAll > $lawHour){//如果实到小时数超过法定小时数，则按1.5倍计算加班薪水
			$outHour = round($hourAll - $lawHour,2);//加班小时数
			$basePay = round($job['basePay'] + $outHour * $job['basePay'] * 1 / $ymh,2);
			$subsidy = round($job['subsidy'] + $outHour * $job['subsidy'] * 1 / $ymh,2);
		}else{
			$outHour = 0;
			if($lawHour == 0){
				$basePay = $subsidy = 0;
			}else{
				$basePay = round($hourAll * $job['basePay'] / $lawHour,2);
				$subsidy = round($hourAll * $job['subsidy'] / $lawHour,2);
			}
		}
		//应发工资
		$money = $basePay + $subsidy;
		//罚款
		$fine = 0;
		//迟到处罚
		if($calendar['lateNum'] > 0){
			$fine += $lateMoney = $calendar['lateNum']*20-10;
		}else{
			$lateMoney = 0;
		}
		//旷工罚款
		if($calendar['leave'] > 0){
			$fine += $leaveMoney = round($calendar['leave'] * ($job['basePay'] + $job['subsidy']) / $lawHour,2);
		}else{
			$leaveMoney = 0;
		}
		//全勤奖
		if($fine == 0 and $hourAll >= $lawHour){
			$fullAttendance = para("fullAttendance");
		}else{
			$fullAttendance = 0;
		}
		//处罚和奖励后实发工资
		$pay = round($money - $fine + $fullAttendance,2);
		//基本信息
		$json['month'] = $data['month'];//月份
		$json['calendar'] = $calendar['tr'];//标记
		$json['ico'] = root.$data['staff']['ico'];//头像
		$json['name'] = $data['staff']['name'];//姓名
		$json['job'] = $department['type']."~".$department['name']."~".$job['name'];//职位
		$json['ymh'] = $ymh;//本年每月平均工作小时数
		$json['basePay'] = $job['basePay'];//基本工资
		$json['subsidy'] = $job['subsidy'];//岗位津贴
		$json['money'] = $data['staff']['money'];//会计账户
		$json['lastMoney'] = $data['staff']['lastMoney'];//结算账户
		//本月考勤
		$json['hourAll'] = $hourAll;//本月实到小时数
		$json['lawHour'] = $lawHour;//本月应到小时数
		$json['workAddHour'] = $workAddHour;//本月加班小时数
		$json['outHour'] = $outHour;//本月超出法定小时数
		$json['lateNum'] = $calendar['lateNum'];//迟到次数
		$json['lateMoney'] = $lateMoney;//迟到处罚金额
		$json['leave'] = $calendar['leave'];//旷工小时数
		$json['leaveMoney'] = $leaveMoney;//旷工处罚金额
		//本月工资
		$json['basePayMoon'] = $basePay;//基本工资
		$json['subsidyMoon'] = $subsidy;//岗位津贴
		$json['fullAttendance'] = $fullAttendance;//全勤奖
		$json['pay'] = $pay;//实得工资
		//提示
		$json['workOvertimeText'] = "当月超出法定小时数记为加班，计算公式：（（基本工资+岗位津贴）/本年每月平均工作小时数）*本月实际加班小时数*1.5";//加班备注
		$json['fullAttendanceText'] = "当月无考勤处罚且达到法定工作小时数可获得全勤奖";//全勤奖备注
		$json['warn'] = "success";
		//返回
		return $json;
	}
	/*组合日历*/
	public function calendar($data){
		$staff = $data['staff'];
		//本月天数
		$dayNum = date('t',strtotime($data['month']));
		$result['lastDay'] = $data['month']."-".$dayNum;//当月最后一天
		//本月工作日
		$workMoon = date("Ym",strtotime($data['month']));
		$workDaySql = query("workDay"," moon = '$workMoon' ");
		$workDay = json_decode($workDaySql['workDay'],true);
		$result['workDayNum'] = count($workDay);//当月工作天数
		//打卡节点
		$workTime['morningStart'] = para("workMorningStart");//上午上班时间
		$workTime['morningEnd'] = para("workMorningEnd");//上午下班时间
		$workTime['afternoonStart'] = para("workAfternoonStart");//下午上班时间
		$workTime['afternoonEnd'] = para("workAfternoonEnd");//下班时间
		//迟到次数
		$result['lateNum'] = $result['workHour'] = $result['leave'] = 0;
		//生成日历
		$week = date("N",strtotime($data['month']."-01"));//星期几，初始化为当月一号
		$result['tr'] = array();
		for($n=1;$n<=$dayNum;$n++){
			//当日考勤记录
			$today = $data['month']."-".sprintf("%02u",$n);
			$todayStart = $today." 00:00:00";
			$todayEnd = $today." 23:59:59";
			$sign = array();
			$sql = find(array("table" => "workSign","where" => " stid = '$staff[stid]' and signTime >= '$todayStart' and signTime <= '$todayEnd' order by signTime "));
			foreach($sql['array'] as $array){
				$sign[$array['signTime']] = array("type" => "考勤机");
			}
			//当日补卡记录
			$note = array();
			$sql = find(array("table" => "workSignAdd","where" => " stid = '$staff[stid]' and signTime >= '$todayStart' and signTime <= '$todayEnd' and workFlow = '已通过' order by signTime "));
			foreach($sql['array'] as $array){
				$sign[$array['signTime']] = array("type" => "补","text" => $array['text']);
				$note[] = array(
					"title" => "补卡",//标题
					"time" => date("H:i:s",strtotime($array['signTime'])),//时间
					"text" => $array['text'],//备注
				);
			}
			//当日请假记录
			$morningStart = $today." ".$workTime['morningStart'];//当日上午上班时间
			$afternoonEnd = $today." ".$workTime['afternoonEnd'];//当日下午下班时间
			$holiday = array();//请假数组
			$sql = find(array("table" => "workHoliday","where" => " stid = '$staff[stid]' and startTime <= '$afternoonEnd' and endTime >= '$morningStart' and workFlow = '已通过' order by startTime "));
			foreach($sql['array'] as $array){
				$holiday[] = array("type" => $array['type'],"start" => $array['startTime'],"end" => $array['endTime'],"text" => $array['text']);
				$note[] = array(
					"title" => "请假",
					"time" => date("H:i:s",strtotime($array['startTime']))."-".date("H:i:s",strtotime($array['endTime'])),
					"text" => $array['text'],
				);
			}
			//当日加班记录，根据实际加班开始时间划分加班日期
			$sql = find(array("table" => "work_add","where" => " stid = '$staff[stid]' and timeStart > '$todayStart' and timeStart <= '$todayEnd' and workFlow = '已通过' order by time "));
			$add = "否";
			$addHour = 0;//当日加班总小时数
			foreach($sql['array'] as $array){
				$addHour += $array['hour'];
				$add = "是";
				if($array['timeStart'] < $todayEnd and $todayEnd < $array['timeEnd']){//如果加班超过凌晨
					$sign["23:59:59"] = array("type" => "加","text" => $array['text']);
				}
				$note[] = array(
					"title" => "加班",
					"time" => date("H:i:s",strtotime($array['timeStart']))."-".date("H:i:s",strtotime($array['timeEnd'])),
					"text" => $array['text'],
				);
			}
			//打卡时间顺序排列
			ksort($sign);
			//今天打卡的次数
			$signNum = count($sign);
			//打印日历
			if(in_array($n,(array)$workDay)){//查询是否为工作日
				$signRsult = $this->sign(array("sign" => $sign,"workTime" => $workTime,"today" => $today,"holiday" => $holiday,"add" => $add,"staff" => $staff));
				$result['marry'] += $signRsult['marry'];//累加本月婚假小时数
				$result['lateNum'] += $signRsult['lateNum'];//迟到次数
				$result['workHour'] += $signRsult['workHour'];//工作小时数
				if($signRsult['leave'] > 0){
					$result['leave'] += $signRsult['leave'];//旷工小时数
				}
				$result['tr'][] = array(
					"day" => $n,//日期
					"workDay" => "是",//工作日
					"hour" => $signRsult['workHour'] + $addHour,//当日工作小时数
					"signNum" => $signNum,//打卡次数
					"start" => $signRsult['start'],//上班签到数组
					"end" => $signRsult['end'],//下班签到数组
					"note" => $note,//当日考勤备注
				);
			}else{
				$startTab['signAdd'] = $endTab['signAdd'] = $endTab['add'] = "否";
				if($signNum == 0){
					$startTime = $endTime = "休息";
				}elseif($signNum == 1){
					$signStartTime = key($sign);
					if($sign[$signStartTime]['type'] == "补"){
						$startTab['signAdd'] = "是";
					}
					$startTime = date("H:i:s",strtotime($signStartTime));
					$endTime = "缺卡";
				}else{
					//上班
					$signStartTime = key($sign);
					if($sign[$signStartTime]['type'] == "补"){
						$startTab['signAdd'] = "是";
					}
					$startTime = date("H:i:s",strtotime($signStartTime));
					//下班
					end($sign);//把指针切换到数组最后一条记录
					$signEndTime = key($sign);
					if($sign[$signEndTime]['type'] == "补"){
						$endTab['signAdd'] = "是";
					}
					$endTab['add'] = $add;
					$endTime = date("H:i:s",strtotime($signEndTime));
				}
				$result['tr'][] = array(
					"day" => $n,//日期
					"workDay" => "否",//工作日
					"hour" => $addHour,//当日工作小时数
					"signNum" => $signNum,//打卡次数
					"start" => array("time" => $startTime,"tab" => $startTab),//上班签到数组
					"end" => array("time" => $endTime,"tab" => $endTab),//上班签到数组
					"note" => $note,//当日考勤备注
				);
			}
		}
		//返回
		return $result;
	}
	/*分析打卡时间*/
	public function sign($data){
		//请假分析
		$morning['start'] = strtotime($data['today']." ".$data['workTime']['morningStart']);//上午上班时间戳
		$morning['end'] = strtotime($data['today']." ".$data['workTime']['morningEnd']);//上午下班时间戳
		$afternoon['start'] = strtotime($data['today']." ".$data['workTime']['afternoonStart']);//下午上班时间戳
		$afternoon['end'] = strtotime($data['today']." ".$data['workTime']['afternoonEnd']);//下午下班时间戳
		//过滤上午上班两小时前的签到，可能为上一天的加班打卡
		foreach($data['sign'] as $key => $value){
			$signStamp = strtotime($key);//签到时间戳
			if($signStamp < $morning['start']-3600*2){
				unset($data['sign'][$key]);
			}
		}
		//打卡时间分析
		$signNum = count($data['sign']);//今天打卡的次数
		$result['lateNum'] = 0;//迟到次数
		$result['leave'] = 0;//旷工小时数
		$result['workHour'] = 0;//实到小时数
		$holiday = $this->holiday(array("start" => $morning['start'],"end" => $afternoon['end'],"holiday" => $data['holiday'],"morning" => $morning,"afternoon" => $afternoon));//今天请假合计小时数和所有请假标记
		$result['marry'] = $holiday['marry'];//今天合计婚假小时数;
		$result['start']['tab']['holiday'] = $holiday['start'];
		$result['end']['tab']['holiday'] = $holiday['end'];
		$result['start']['tab']['late'] = $result['start']['tab']['leave'] = $result['start']['tab']['signAdd'] = "否";
		$result['end']['tab']['quit'] = $result['end']['tab']['leave'] = $result['end']['tab']['signAdd'] = "否";
		$result['end']['tab']['add'] = $data['add'];
		if($holiday['hour'] >= 8){//全天请假
			$result['start']['time'] = $result['end']['time'] = "请假";
		}elseif(strtotime($data['today']) >= time()){//未来时间
			$result['start']['time'] = $result['end']['time'] = "未来";
		}elseif(strtotime($data['today']) < strtotime($data['staff']['entryTime'])){//今天未入职
			$result['start']['time'] = $result['end']['time'] = "未入职";
		}elseif($data['staff']['state'] == "离职" and strtotime($data['staff']['quitTime']) < strtotime($data['today'])){//今天已离职
			$result['start']['time'] = $result['end']['time'] = "已离职";
		}elseif($signNum == 0){
			$result['start']['time'] = $result['end']['time'] = "缺卡";
			$result['end']['tab']['leave'] = "是";
			$result['leave'] = 8 - $holiday['hour'];
		}elseif($signNum == 1){
			$signTime = key($data['sign']);//唯一打卡时间
			$signStamp = strtotime($signTime);//签到时间戳
			$signTime = date("H:i:s",strtotime($signTime));
			if($data['today'] != date("Y-m-d")){
				$result['leave'] = 8 - $holiday['hour'];
			}
			if($data['sign'][$signTime]['type'] == "补"){
				$signAdd = "是";
			}else{
				$signAdd = "否";
			}
			if($afternoon['end'] <= $signStamp){//如果是下班之后打的卡
				$result['start']['time'] = "缺卡";
				$result['end']['time'] = $signTime;
				$result['end']['tab']['signAdd'] = $signAdd;
			}elseif($signStamp <= $morning['start']){//如果是上班之前打的卡
				$result['start']['time'] = $signTime;
				$result['start']['tab']['signAdd'] = $signAdd;
				$result['end']['time'] = "缺卡";
			}elseif($signStamp <= $morning['start']+60*30){//迟到半小时内
				$result['lateNum'] = 1;
				$result['start']['time'] = $signTime;
				$result['start']['tab']['signAdd'] = $signAdd;
				$result['start']['tab']['late'] = "是";
				$result['end']['time'] = "缺卡";
			}else{//迟到半小时后
				$result['start']['time'] = $signTime;
				$result['start']['tab']['signAdd'] = $signAdd;
				$result['end']['time'] = "缺卡";
			}
		}else{
			//上班签到时间戳
			$signStartTime = key($data['sign']);
			$signStartStamp = strtotime($signStartTime);
			$result['start']['time'] = date("H:i:s",strtotime($signStartTime));
			if($data['sign'][$signStartTime]['type'] == "补"){
				$result['start']['tab']['signAdd'] = "是";
			}
			//下班签到时间戳
			end($data['sign']);//把指针切换到数组最后一条记录
			$signEndTime = key($data['sign']);
			$signEndStamp = strtotime($signEndTime);
			$result['end']['time'] = date("H:i:s",strtotime($signEndTime));
			if($data['sign'][$signEndTime]['type'] == "补"){
				$result['end']['tab']['signAdd'] = "是";
			}
			//判断
			if($signEndStamp <= $morning['start']){//仅在上班前打了两次卡
				if($data['today'] != date("Y-m-d")){
					$result['leave'] = 8 - $holiday['hour'];
				}
				$result['end']['time'] = "缺卡";
				$result['end']['tab']['signAdd'] = "否";
			}elseif($morning['end'] <= $signStartStamp and $morning['end'] <= $signEndStamp and $signStartStamp <= $afternoon['start'] and $signEndStamp <= $afternoon['start']){//两次打卡时间都是中午
				$result['leave'] = 8 - $holiday['hour'];
			}elseif($afternoon['end'] <= $signStartStamp){//仅在下班后打了两次卡
				$result['leave'] = 8 - $holiday['hour'];
				$result['start']['time'] = "缺卡";
				$result['start']['tab']['signAdd'] = "否";
			}else{//两次打卡都在上班时间或正常打卡
				$result['workHour'] = $this->noon(array("start" => $signStartStamp,"end" => $signEndStamp,"morning" => $morning,"afternoon" => $afternoon));//今天签到小时数
				$holidayIn = $this->holiday(array("start" => $signStartStamp,"end" => $signEndStamp,"holiday" => $data['holiday'],"morning" => $morning,"afternoon" => $afternoon));//上下班签到之间请假
				$result['workHour'] -= $holidayIn['hour'];//实际上班小时数
				//上班签到标记
				if($signStartStamp <= $morning['start']){//无迟到
				}else{//有迟到
					//上班签到前缺勤小时数
					$leaveStart = $this->noon(array("start" => $morning['start'],"end" => $signStartStamp,"morning" => $morning,"afternoon" => $afternoon));
					//上班签到前的总请假小时数
					$holidayStart = $this->holiday(array("start" => $morning['start'],"end" => $signStartStamp,"holiday" => $data['holiday'],"morning" => $morning,"afternoon" => $afternoon));
					if($signStartStamp <= $morning['start']+1800 and $leaveStart != $holidayStart['hour']){//迟到半小时内，且签到前缺勤小时数不等于签到前请假小时数
						$result['lateNum'] = 1;
						$result['start']['tab']['late'] = "是";
					}elseif($leaveStart > $holidayStart['hour']){//如果有旷工
						$result['leave'] = round($leaveStart - $holidayStart['hour'],2);
						$result['start']['tab']['leave'] = "是";
					}
				}
				//下班签到标记
				if($afternoon['end'] <= $signEndStamp){//无早退
				}else{//有早退
					//下班签到后缺勤小时数
					$leaveEnd = $this->noon(array("start" => $signEndStamp,"end" => $afternoon['end'],"morning" => $morning,"afternoon" => $afternoon));
					//下班签到后的总请假小时数
					$holidayEnd = $this->holiday(array("start" => $signEndStamp,"end" => $afternoon['end'],"holiday" => $data['holiday'],"morning" => $morning,"afternoon" => $afternoon));
					//如果有旷工，且不是因为当天离职早走
					if($data['today'] == $data['staff']['quitTime']){
						$result['end']['tab']['quit'] = "是";
					}elseif($leaveEnd > $holidayEnd['hour']){
						$result['leave'] += $leaveEnd - $holidayEnd['hour'];
						$result['end']['tab']['leave'] = "是";
					}
				}
			}
		}				
		//返回
		return $result;
	}
	/*本年每月平均法定小时数
	$data = array(
		"month" => "查询的月份",
	);
	*/
	public function ymh($data){
		//年份
		$year = date("Y",strtotime($data['month']));
		//该年工作天数
		$moonStart = $year."01";
		$moonEnd = $year."12";
		$workDay = find(array("table" => "workDay","where" => " moon >= '$moonStart' and moon <= '$moonEnd' order by moon "));
		$work = 0;
		foreach($workDay['array'] as $array){
			$work += count(json_decode($array['workDay'],true));
		}
		//平均每月小时数
		$hour = round($work*8/12,2);
		//返回
		return $hour;
	}
	/*查询某段时间的请假小时数
	$data = array(
		"start" => "查询请假小时数的开始时间",
		"end" => "查询请假小时数的结束时间",
		"holiday" => "今日的所有请假记录",
		"morning" => 上午上下班时间戳,
		"afternoon" => 下午上下班时间戳,
	);
	*/
	public function holiday($data){
		//赋值
		$holiday['hour'] = 0;//请假小时数
		$holiday['marry'] = 0;//婚假小时数
		$holiday['start'] = $holiday['end'] = "否";//上午和下午请假标记
		//循环
		foreach($data['holiday'] as $array){
			$holidayStartStamp = strtotime($array['start']);//请假开始时间戳
			$holidayEndStamp = strtotime($array['end']);//请假结束时间戳
			//请假标记
			if($holidayStartStamp < $data['morning']['end']){
				$holiday['start'] = "是";
			}else{
				$holiday['end'] = "是";
			}
			//修正请假的开始和结束时间
			if($holidayStartStamp < $data['start']){
				$holidayStartStamp = $data['start'];
			}
			if($data['end'] < $holidayEndStamp){
				$holidayEndStamp = $data['end'];
			}
			//修正后请假开始时间和结束时间都在查询时间段中，且请假开始时间小于结束时间，说明该请假时间与查询时间存在交集
			if($holidayStartStamp < $holidayEndStamp){
				$hour += $this->noon(array("start" => $holidayStartStamp,"end" => $holidayEndStamp,"morning" => $data['morning'],"afternoon" => $data['afternoon']));
				$holiday['hour'] = $hour;
				if($array['type'] == "婚假"){
					$holiday['marry'] = $hour;
				}
			}
		}
		//返回
		return $holiday;
	}
	/*扣除中午时间
	$data = array(
		"start" => 开始时间,
		"end" => 结束时间,
		"morning" => 上午上下班时间戳,
		"afternoon" => 下午上下班时间戳,
	);
	*/
	public function noon($data){
		//修正开始和结束时间
		if($data['start'] < $data['morning']['start']){
			$data['start'] = $data['morning']['start'];
		}
		if($data['afternoon']['end'] < $data['end']){
			$data['end'] = $data['afternoon']['end'];
		}
		//计算小时数
		if(in_array("",$data)){
			$hour = 0;
		}elseif($data['end'] < $data['start']){//如果结束时间比开始时间小
			$hour = 0;
		}elseif($data['end'] < $data['morning']['start'] or $data['afternoon']['end'] < $data['start']){//如果两次打卡时间都在上午上班之前或下午下班之后
			$hour = 0;
		}elseif($data['start'] <= $data['morning']['end'] and $data['afternoon']['start'] <= $data['end']){//包含整个中午
			$hour = round(($data['end'] - $data['start'])/3600,2) - 1;
		}elseif($data['start'] <= $data['morning']['end'] and $data['morning']['end'] <= $data['end'] and $data['end'] <= $data['afternoon']['start']){//开始时间为上午上班时间，中午结束
			$hour = round(($data['morning']['end'] - $data['start'])/3600,2);
		}elseif($data['morning']['end'] <= $data['start'] and $data['start'] <= $data['afternoon']['start'] and $data['afternoon']['start'] <= $data['end']){//中午休息时间开始，下午上班期间结束
			$hour = round(($data['end'] - $data['afternoon']['start'])/3600,2);
		}elseif($data['morning']['end'] <= $data['start'] and $data['morning']['end'] <= $data['end'] and $data['start'] <= $data['afternoon']['start'] and $data['end'] <= $data['afternoon']['start']){//时间段在中午
			$hour = 0;
		}else{//时间段在上午或下午
			$hour = round(($data['end'] - $data['start'])/3600,2);
		}
		//返回
		return $hour;
	}

}


?>